package com.anjie.powerproject.strategy.utils;

import lombok.Data;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * 由于项目中涉及大量时间/日期的计算、转换操作，这里将这些操作总结在此
 */
@Component
public class DateUtils {
    // 1. 各种不同的SimpleDateFormat
    public static SimpleDateFormat ymdFormat = new SimpleDateFormat("yyyy-MM-dd");
    public static SimpleDateFormat mdFormat = new SimpleDateFormat("MM-dd");
    public static SimpleDateFormat mFormat = new SimpleDateFormat("MM");
    public static SimpleDateFormat ymdhFormat = new SimpleDateFormat("yyyy-MM-dd HH");
    public static SimpleDateFormat ymdhmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    public static SimpleDateFormat mdhFormat = new SimpleDateFormat("MM-dd HH");
    public static SimpleDateFormat mdhmFormat = new SimpleDateFormat("MM-dd HH:mm");
    public static SimpleDateFormat hmFormat = new SimpleDateFormat("HH:mm");

    public static SimpleDateFormat ymdFormat2 = new SimpleDateFormat("yyyyMMdd");

    // 2. 各种Calendar方法
    // 2.1 获取前x日或后x日的时间(offset为正表示后、反之表示向前)
    public static Calendar plusOrMinusDay(Calendar calendar, int offset) {
        calendar.add(Calendar.DATE, offset);
        return calendar;
    }
    public static Calendar plusOrMinusDay(Date date, int offset) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        return plusOrMinusDay(calendar, offset);
    }

    // 2.2 获取前x小时或后x小时的时间
    public static Calendar plusOrMinusHour(Calendar calendar, int offset) {
        calendar.add(Calendar.HOUR, offset);
        return calendar;
    }
    public static Calendar plusOrMinusHour(Date date, int offset) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        return plusOrMinusHour(calendar, offset);
    }

    // 2.3 获取前x分钟或后x分钟的时间
    public static Calendar plusOrMinusMinute(Calendar calendar, int offset) {
        calendar.add(Calendar.MINUTE, offset);
        return calendar;
    }
    public static Calendar plusOrMinusMinute(Date date, int offset) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        return plusOrMinusMinute(calendar, offset);
    }

    // 3 日期时间转字符串 / 字符串转日期时间
    public static String getLocalDateString(SimpleDateFormat dateFormat, Date date) {
        return dateFormat.format(date);
    }
    public static Date parseStringToDate(SimpleDateFormat dateFormat, String dateStr) throws ParseException {
        return dateFormat.parse(dateStr);
    }

    // 4 Date转Calendar
    public static Calendar dateToCalender(Date date) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        return calendar;
    }

    // 5 获取指定日期指定小时的时间
    public static Calendar getDateWithHour(Date date, Integer hour) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar;
    }

    // 6 获取指定日期指定分钟的时间
    public static Calendar getDateWithMinute(Date date, Integer minute) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar;
    }

    // 7 获取指定日期指定小时，指定分钟的时间
    public static Calendar getDateWithHourAndMinute(Date date, Integer hour, Integer minute) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar;
    }

    // 判断一个时间是否在另一个时间之前
    public static boolean before(Date t1, Date t2) {
        Calendar t1Calender = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        t1Calender.setTime(t1);

        Calendar t2Calener = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        t2Calener.setTime(t2);
        return t1Calender.before(t2Calener);
    }

    // 判断一个时间是否在另一个时间之后
    public static boolean after(Date t1, Date t2) {
        Calendar t1Calender = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        t1Calender.setTime(t1);

        Calendar t2Calener = Calendar.getInstance(TimeZone.getTimeZone("Asia/Shanghai"));
        t2Calener.setTime(t2);
        return t1Calender.after(t2Calener);
    }

    public static boolean between(Date t, Date t1, Date t2) {
        return t.before(t2) && t.after(t1);
    }

    // 计算两个时间点之间有几天
    public static int count(Date start, Date end) {
        return (int)((end.getTime() - start.getTime()) / 86400000 + 1);
    }

    public static TimeProperty getPropertyByDateStr(String date) throws ParseException {
        TimeProperty timeProperty = new TimeProperty();
        Calendar calendar = dateToCalender(ymdFormat.parse(date));

        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        timeProperty.setHoliday(dayOfWeek == 1 || dayOfWeek == 7 ? "1" : "0");
        timeProperty.setDayOfWeek(Integer.toString(dayOfWeek));
        timeProperty.setWeekOfYear(Integer.toString(calendar.get(Calendar.WEEK_OF_YEAR)));
        int month = calendar.get(Calendar.MONTH);
        timeProperty.setSeason(Integer.toString(month % 3 == 0 ? month / 3 : month / 3 + 1));
        timeProperty.setMonth(Integer.toString(calendar.get(Calendar.MONTH)));
        timeProperty.setDay(Integer.toString(calendar.get(Calendar.DATE)));

        return timeProperty;
    }

    public static class TimeProperty {
        private String holiday;
        private String weekOfYear;
        private String dayOfWeek;
        private String season;
        private String month;
        private String day;

        public String getHoliday() {
            return holiday;
        }

        public void setHoliday(String holiday) {
            this.holiday = holiday;
        }

        public String getWeekOfYear() {
            return weekOfYear;
        }

        public void setWeekOfYear(String weekOfYear) {
            this.weekOfYear = weekOfYear;
        }

        public String getDayOfWeek() {
            return dayOfWeek;
        }

        public void setDayOfWeek(String dayOfWeek) {
            this.dayOfWeek = dayOfWeek;
        }

        public String getSeason() {
            return season;
        }

        public void setSeason(String season) {
            this.season = season;
        }

        public String getMonth() {
            return month;
        }

        public void setMonth(String month) {
            this.month = month;
        }

        public String getDay() {
            return day;
        }

        public void setDay(String day) {
            this.day = day;
        }
    }
}